package com.cmc.cloud.cmclink.doc.service.impl.special;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cmc.cloud.cmclink.doc.api.document.emums.*;
import com.cmc.cloud.cmclink.doc.convert.SpecialCargoVoyageConvert;
import com.cmc.cloud.cmclink.doc.dto.SpecialModifyVelVoyDto;
import com.cmc.cloud.cmclink.doc.entity.*;
import com.cmc.cloud.cmclink.doc.mapper.*;
import com.cmc.cloud.cmclink.doc.service.SpecialCargoApplyService;
import com.cmc.cloud.cmclink.doc.service.special.SpecialModifyVelVoyService;
import com.cmc.cloud.cmclink.doc.vo.sovo.attachmentvo.AttachmentUpdateReqVO;
import com.cmc.cloud.cmclink.doc.vo.special.externalapivo.CntrAndDgBaseVO;
import com.cmc.cloud.cmclink.doc.vo.special.externalapivo.CntrAndFlexiBaseVO;
import com.cmc.cloud.cmclink.doc.vo.special.externalapivo.CntrAndOdoBaseVO;
import com.cmc.cloud.cmclink.doc.vo.special.externalapivo.CntrAndOogBaseVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargoapplyvo.CreateOrCommitSpcReqVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargoapplyvo.SpecialCargoVoyageUpdateReqVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargocasvo.CasCreateOrUpdateVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargocntrvo.SpecialCargoCntrBaseVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargodgpackingvo.PackingCreateOrUpdateVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargodgvo.SpecialCargoDgBaseVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargoflexivo.SpecialCargoFlexiBaseVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargoodovo.SpecialCargoOdoBaseVO;
import com.cmc.cloud.cmclink.doc.vo.specialcargooogvo.SpecialCargoOogBaseVO;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lzp
 * @date 2025/10/10 16:07
 * @description
 */
@Service
public class SpecialModifyVelVoyServiceImpl implements SpecialModifyVelVoyService {

    @Resource
    private SpecialCargoApplyMapper specialCargoApplyMapper;

    @Resource
    private SpecialCargoVoyageMapper specialCargoVoyageMapper;

    @Resource
    private SpecialCargoCntrMapper specialCargoCntrMapper;

    @Resource
    private SpecialCargoOogMapper specialCargoOogMapper;

    @Resource
    private SpecialCargoOdoMapper specialCargoOdoMapper;

    @Resource
    private SpecialCargoDgMapper specialCargoDgMapper;

    @Resource
    private SpecialCargoFlexiMapper specialCargoFlexiMapper;

    @Resource
    private SpecialCargoDgPackingMapper specialCargoDgPackingMapper;

    @Resource
    private SpecialCargoCasMapper specialCargoCasMapper;

    @Resource
    private AttachmentMapper attachmentMapper;

    @Resource
    private CargoCntrTypeRelationMapper cargoCntrTypeRelationMapper;

    @Resource
    private SpecialCargoDgExtMapper specialCargoDgExtMapper;

    @Resource
    private SpecialCargoApplyService specialCargoApplyService;

    @Resource
    private SoMapper soMapper;

    /**
     * 根据审批结果处理,审批通过为true,拒绝的时候不会调用该方法，在原拒绝的逻辑中有做更新拒绝的逻辑所以不会调用，取消修改申请时调用该方法approve=false这时需要做删除操作
     *
     * @param approve
     * @param oldSoId
     * @param newSoId
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateSpecialApplyInfo(boolean approve, Long oldSoId, Long newSoId) {
        if (approve) {
            LambdaQueryWrapperX<SpecialCargoApplyDO> oldApply = new LambdaQueryWrapperX<>();
            oldApply.eq(SpecialCargoApplyDO::getSoId, oldSoId).last(" limit 1");
            SpecialCargoApplyDO specialCargoApplyDoOld = specialCargoApplyMapper.selectOne(oldApply);
            if (null == specialCargoApplyDoOld) {
                return;
            }
            specialCargoApplyMapper.deleteById(specialCargoApplyDoOld);
        } else {
            LambdaQueryWrapperX<SpecialCargoApplyDO> newApply = new LambdaQueryWrapperX<>();
            newApply.eq(SpecialCargoApplyDO::getSoId, newSoId).last(" limit 1");
            SpecialCargoApplyDO specialCargoApplyDoNew = specialCargoApplyMapper.selectOne(newApply);
            if (null == specialCargoApplyDoNew) {
                return;
            }
            specialCargoApplyMapper.deleteById(specialCargoApplyDoNew);
        }
    }

    /**
     * 客户发起修改申请并且修改了船名航次，特种货的处理
     * 1.SO是草稿状态时直接更新特种货数据第一段line的船名航次
     * 2.SO是已确认状态时插入一条数据
     *
     * @param specialModifyVelVoyDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void specidalModifyVelVoy(SpecialModifyVelVoyDto specialModifyVelVoyDto) {
        LambdaQueryWrapperX<SpecialCargoApplyDO> lambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        lambdaQueryWrapperX.eq(SpecialCargoApplyDO::getSoId, specialModifyVelVoyDto.getOldSoId()).last(" limit 1");
        SpecialCargoApplyDO specialCargoApplyDo = specialCargoApplyMapper.selectOne(lambdaQueryWrapperX);
        if (null == specialCargoApplyDo) {
            return;
        }
        if (SoStatusEnum.BookingDraft.getValue().equals(specialModifyVelVoyDto.getOldSoStatus()) && ApplyStatusEnum.EDIT.getValue().equals(specialCargoApplyDo.getApplyStatus())) {
            this.updateVolVoyInfo(specialCargoApplyDo, specialModifyVelVoyDto);
        }
        boolean check = SoStatusEnum.BookingConfirmed.getValue().equals(specialModifyVelVoyDto.getOldSoStatus()) && ApplyStatusEnum.APPROVED.getValue().equals(specialCargoApplyDo.getApplyStatus());
        if (check) {
            this.dealSpecialModifyVelVoy(specialCargoApplyDo, specialModifyVelVoyDto);
        }
    }

    private void updateVolVoyInfo(SpecialCargoApplyDO specialCargoApplyDo, SpecialModifyVelVoyDto specialModifyVelVoyDto) {
        LambdaQueryWrapperX<SpecialCargoVoyageDO> specialCargoVoyageDoLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        specialCargoVoyageDoLambdaQueryWrapperX.eq(SpecialCargoVoyageDO::getApplyId, specialCargoApplyDo.getId());
        specialCargoVoyageMapper.delete(specialCargoVoyageDoLambdaQueryWrapperX);
        List<SpecialCargoVoyageDO> specialCargoVoyageDo = SpecialCargoVoyageConvert.INSTANCE.convertSpecialCargoVoyageDos(specialModifyVelVoyDto.getSoVslvoyList());
        specialCargoVoyageDo.forEach(item -> {
            item.setApplyId(specialCargoApplyDo.getId());
            item.setId(null);
        });
        specialCargoVoyageMapper.insertBatch(specialCargoVoyageDo);
    }

    private void dealSpecialModifyVelVoy(SpecialCargoApplyDO specialCargoApplyDo, SpecialModifyVelVoyDto specialModifyVelVoyDto) {
        String applyType = specialCargoApplyDo.getApplyType();
        CreateOrCommitSpcReqVO createOrCommitSpcReqVo = new CreateOrCommitSpcReqVO();
        switch (SpecialEnum.valueOf(applyType)) {
            case ODO:
                createOrCommitSpcReqVo = dealOdoInfo(specialCargoApplyDo, specialModifyVelVoyDto);
                break;
            case FLEXI:
                createOrCommitSpcReqVo = dealFlexiInfo(specialCargoApplyDo, specialModifyVelVoyDto);
                break;
            case DG:
                createOrCommitSpcReqVo = dealDgInfo(specialCargoApplyDo, specialModifyVelVoyDto);
                break;
            default:
                createOrCommitSpcReqVo = dealOogInfo(specialCargoApplyDo, specialModifyVelVoyDto);
        }
        createOrCommitSpcReqVo.setChangeVoyCheck(true);
        specialCargoApplyService.createOrCommitSpc(createOrCommitSpcReqVo);
    }

    /**
     * 处理ODO
     *
     * @param specialCargoApplyDo
     * @param specialModifyVelVoyDto
     * @return
     */
    public CreateOrCommitSpcReqVO dealOdoInfo(SpecialCargoApplyDO specialCargoApplyDo, SpecialModifyVelVoyDto specialModifyVelVoyDto) {
        CreateOrCommitSpcReqVO createOrCommitSpcReqVo = new CreateOrCommitSpcReqVO();
        //查询箱信息
        List<SpecialCargoCntrDO> cntrDoList = this.querySpecialCntrInfo(specialCargoApplyDo.getId());
        //查询附件信息
        List<AttachmentDO> attachmentDoList = this.querySpecialAttachInfo(specialCargoApplyDo.getId());
        //查询船名航次信息
        List<SpecialCargoVoyageDO> voyageDoList = this.querySpecialVelVoyInfo(specialCargoApplyDo.getId(), specialModifyVelVoyDto);
        //查询odo
        List<Long> cntrIds = cntrDoList.stream().map(SpecialCargoCntrDO::getId).collect(Collectors.toList());
        List<SpecialCargoOdoDO> cargoOdoDoList = this.querySpecialOdoInfo(cntrIds);
        Map<Long, List<SpecialCargoOdoDO>> listMap = cargoOdoDoList.stream().collect(Collectors.groupingBy(SpecialCargoOdoDO::getCntrId));
        specialCargoApplyDo.setSoId(specialModifyVelVoyDto.getNewSoId());
        createOrCommitSpcReqVo = BeanUtil.copyProperties(specialCargoApplyDo, createOrCommitSpcReqVo.getClass(), "id");
        createOrCommitSpcReqVo.setCommitOrSave(true);
        createOrCommitSpcReqVo.setPartnerFlag(false);
        createOrCommitSpcReqVo.setApplyStatus(ApplyStatusEnum.CHANGEVOYCHECK.getValue());
        //设置4港信息
        SoDO soDo = soMapper.selectById(specialModifyVelVoyDto.getNewSoId());
        createOrCommitSpcReqVo.setPodCode(soDo.getPodCode());
        createOrCommitSpcReqVo.setPolCode(soDo.getPolCode());
        createOrCommitSpcReqVo.setPorCode(soDo.getPorCode());
        createOrCommitSpcReqVo.setDelCode(soDo.getDelCode());
        createOrCommitSpcReqVo.setCurrentPort(soDo.getCurrentPort());

        List<SpecialCargoVoyageUpdateReqVO> spcVoyageInfo = new ArrayList<>(32);
        for (SpecialCargoVoyageDO specialCargoVoyageDo : voyageDoList) {
            SpecialCargoVoyageUpdateReqVO specialCargoVoyageUpdateReqVo = BeanUtil.copyProperties(specialCargoVoyageDo, SpecialCargoVoyageUpdateReqVO.class, "id", "applyId");
            if (ApproveStatusEnum.PENDING.getValue().equals(specialCargoVoyageUpdateReqVo.getRouteApproveStatus())) {
                specialCargoVoyageUpdateReqVo.setRouteApproveStatus(ApprovalStatusEnum.PENDING.getValue());
            }
            if (ApproveStatusEnum.APPROVED.getValue().equals(specialCargoVoyageUpdateReqVo.getRouteApproveStatus())) {
                specialCargoVoyageUpdateReqVo.setRouteApproveStatus(ApprovalStatusEnum.APPROVED.getValue());
            }
            spcVoyageInfo.add(specialCargoVoyageUpdateReqVo);
        }
        createOrCommitSpcReqVo.setSpcVoyageInfo(spcVoyageInfo);
        if (CollectionUtils.isNotEmpty(attachmentDoList)) {
            List<AttachmentUpdateReqVO> spcAttachmentList = new ArrayList<>(32);
            for (AttachmentDO attachmentDo : attachmentDoList) {
                spcAttachmentList.add(BeanUtil.copyProperties(attachmentDo, AttachmentUpdateReqVO.class, "id", "referenceId"));
            }
            createOrCommitSpcReqVo.setSpcAttachmentList(spcAttachmentList);
        }
        //处理ODO自己的信息
        List<CntrAndOdoBaseVO> cntrAndOdoInfos = new ArrayList<>(32);
        for (SpecialCargoCntrDO specialCargoCntrDo : cntrDoList) {
            CntrAndOdoBaseVO cntrAndOdoBaseVo = new CntrAndOdoBaseVO();
            cntrAndOdoBaseVo.setCntrBaseInfo(BeanUtil.copyProperties(specialCargoCntrDo, SpecialCargoCntrBaseVO.class, "id", "applyId"));
            SpecialCargoOdoDO specialCargoOdoDo = listMap.get(specialCargoCntrDo.getId()).get(0);
            cntrAndOdoBaseVo.setOdoBaseInfo(BeanUtil.copyProperties(specialCargoOdoDo, SpecialCargoOdoBaseVO.class, "id", "cntrId"));
            cntrAndOdoInfos.add(cntrAndOdoBaseVo);
        }
        createOrCommitSpcReqVo.setCntrAndOdoInfos(cntrAndOdoInfos);

        return createOrCommitSpcReqVo;
    }

    /**
     * 处理FLEXI
     *
     * @param specialCargoApplyDo
     * @param specialModifyVelVoyDto
     * @return
     */
    public CreateOrCommitSpcReqVO dealFlexiInfo(SpecialCargoApplyDO specialCargoApplyDo, SpecialModifyVelVoyDto specialModifyVelVoyDto) {
        CreateOrCommitSpcReqVO createOrCommitSpcReqVo = new CreateOrCommitSpcReqVO();
        //查询箱信息
        List<SpecialCargoCntrDO> cntrDoList = this.querySpecialCntrInfo(specialCargoApplyDo.getId());
        //查询附件信息
        List<AttachmentDO> attachmentDoList = this.querySpecialAttachInfo(specialCargoApplyDo.getId());
        //查询船名航次信息
        List<SpecialCargoVoyageDO> voyageDoList = this.querySpecialVelVoyInfo(specialCargoApplyDo.getId(), specialModifyVelVoyDto);
        //查询flexi
        List<Long> cntrIds = cntrDoList.stream().map(SpecialCargoCntrDO::getId).collect(Collectors.toList());
        List<SpecialCargoFlexiDO> cargoOdoDoList = this.querySpecialFlexInfo(cntrIds);
        Map<Long, List<SpecialCargoFlexiDO>> listMap = cargoOdoDoList.stream().collect(Collectors.groupingBy(SpecialCargoFlexiDO::getCntrId));
        specialCargoApplyDo.setSoId(specialModifyVelVoyDto.getNewSoId());
        createOrCommitSpcReqVo = BeanUtil.copyProperties(specialCargoApplyDo, createOrCommitSpcReqVo.getClass(), "id");
        createOrCommitSpcReqVo.setCommitOrSave(true);
        createOrCommitSpcReqVo.setPartnerFlag(false);
        //设置4港信息
        SoDO soDo = soMapper.selectById(specialModifyVelVoyDto.getNewSoId());
        createOrCommitSpcReqVo.setPodCode(soDo.getPodCode());
        createOrCommitSpcReqVo.setPolCode(soDo.getPolCode());
        createOrCommitSpcReqVo.setPorCode(soDo.getPorCode());
        createOrCommitSpcReqVo.setDelCode(soDo.getDelCode());
        createOrCommitSpcReqVo.setCurrentPort(soDo.getCurrentPort());

        createOrCommitSpcReqVo.setApplyStatus(ApplyStatusEnum.CHANGEVOYCHECK.getValue());

        List<SpecialCargoVoyageUpdateReqVO> spcVoyageInfo = new ArrayList<>(32);
        for (SpecialCargoVoyageDO specialCargoVoyageDo : voyageDoList) {
            SpecialCargoVoyageUpdateReqVO specialCargoVoyageUpdateReqVo = BeanUtil.copyProperties(specialCargoVoyageDo, SpecialCargoVoyageUpdateReqVO.class, "id", "applyId");
            if (ApproveStatusEnum.PENDING.getValue().equals(specialCargoVoyageUpdateReqVo.getRouteApproveStatus())) {
                specialCargoVoyageUpdateReqVo.setRouteApproveStatus(ApprovalStatusEnum.PENDING.getValue());
            }
            if (ApproveStatusEnum.APPROVED.getValue().equals(specialCargoVoyageUpdateReqVo.getRouteApproveStatus())) {
                specialCargoVoyageUpdateReqVo.setRouteApproveStatus(ApprovalStatusEnum.APPROVED.getValue());
            }
            spcVoyageInfo.add(specialCargoVoyageUpdateReqVo);
        }

        createOrCommitSpcReqVo.setSpcVoyageInfo(spcVoyageInfo);
        if (CollectionUtils.isNotEmpty(attachmentDoList)) {
            List<AttachmentUpdateReqVO> spcAttachmentList = new ArrayList<>(32);
            for (AttachmentDO attachmentDo : attachmentDoList) {
                spcAttachmentList.add(BeanUtil.copyProperties(attachmentDo, AttachmentUpdateReqVO.class, "id", "referenceId"));
            }
            createOrCommitSpcReqVo.setSpcAttachmentList(spcAttachmentList);
        }
        List<CntrAndFlexiBaseVO> cntrAndFlexiInfos = new ArrayList<>(32);
        for (SpecialCargoCntrDO specialCargoCntrDo : cntrDoList) {
            CntrAndFlexiBaseVO cntrAndFlexiBaseVo = new CntrAndFlexiBaseVO();
            cntrAndFlexiBaseVo.setCntrBaseInfo(BeanUtil.copyProperties(specialCargoCntrDo, SpecialCargoCntrBaseVO.class, "id", "applyId"));
            SpecialCargoFlexiDO specialCargoFlexiDo = listMap.get(specialCargoCntrDo.getId()).get(0);
            cntrAndFlexiBaseVo.setFlexiBaseInfo(BeanUtil.copyProperties(specialCargoFlexiDo, SpecialCargoFlexiBaseVO.class, "id", "cntrId"));
            cntrAndFlexiInfos.add(cntrAndFlexiBaseVo);
        }
        createOrCommitSpcReqVo.setCntrAndFlexiInfos(cntrAndFlexiInfos);
        return createOrCommitSpcReqVo;
    }


    /**
     * 处理DG
     *
     * @param specialCargoApplyDo
     * @param specialModifyVelVoyDto
     * @return
     */
    public CreateOrCommitSpcReqVO dealDgInfo(SpecialCargoApplyDO specialCargoApplyDo, SpecialModifyVelVoyDto specialModifyVelVoyDto) {
        CreateOrCommitSpcReqVO createOrCommitSpcReqVo = new CreateOrCommitSpcReqVO();
        CntrAndDgBaseVO cntrAndDgBaseVo = new CntrAndDgBaseVO();
        //查询箱信息
        List<SpecialCargoCntrDO> cntrDoList = this.querySpecialCntrInfo(specialCargoApplyDo.getId());
        //查询附件信息
        List<AttachmentDO> attachmentDoList = this.querySpecialAttachInfo(specialCargoApplyDo.getId());
        //查询船名航次信息
        List<SpecialCargoVoyageDO> voyageDoList = this.querySpecialVelVoyInfo(specialCargoApplyDo.getId(), specialModifyVelVoyDto);
        //查询OOG
        List<Long> cntrIds = cntrDoList.stream().map(SpecialCargoCntrDO::getId).collect(Collectors.toList());
        List<SpecialCargoOogDO> cargoOdoDoList = this.queryOogInfo(cntrIds);
        Map<Long, List<SpecialCargoOogDO>> listMap = cargoOdoDoList.stream().collect(Collectors.groupingBy(SpecialCargoOogDO::getCntrId));
        specialCargoApplyDo.setSoId(specialModifyVelVoyDto.getNewSoId());
        createOrCommitSpcReqVo = BeanUtil.copyProperties(specialCargoApplyDo, createOrCommitSpcReqVo.getClass(), "id");
        createOrCommitSpcReqVo.setCommitOrSave(true);
        createOrCommitSpcReqVo.setPartnerFlag(false);
        //设置4港信息
        SoDO soDo = soMapper.selectById(specialModifyVelVoyDto.getNewSoId());
        createOrCommitSpcReqVo.setPodCode(soDo.getPodCode());
        createOrCommitSpcReqVo.setPolCode(soDo.getPolCode());
        createOrCommitSpcReqVo.setPorCode(soDo.getPorCode());
        createOrCommitSpcReqVo.setDelCode(soDo.getDelCode());
        createOrCommitSpcReqVo.setCurrentPort(soDo.getCurrentPort());

        createOrCommitSpcReqVo.setApplyStatus(ApplyStatusEnum.CHANGEVOYCHECK.getValue());
        List<SpecialCargoVoyageUpdateReqVO> spcVoyageInfo = new ArrayList<>(32);
        for (SpecialCargoVoyageDO specialCargoVoyageDo : voyageDoList) {
            SpecialCargoVoyageUpdateReqVO specialCargoVoyageUpdateReqVo = BeanUtil.copyProperties(specialCargoVoyageDo, SpecialCargoVoyageUpdateReqVO.class, "id", "applyId");
            if (ApproveStatusEnum.PENDING.getValue().equals(specialCargoVoyageUpdateReqVo.getRouteApproveStatus())) {
                specialCargoVoyageUpdateReqVo.setRouteApproveStatus(ApprovalStatusEnum.PENDING.getValue());
            }
            if (ApproveStatusEnum.APPROVED.getValue().equals(specialCargoVoyageUpdateReqVo.getRouteApproveStatus())) {
                specialCargoVoyageUpdateReqVo.setRouteApproveStatus(ApprovalStatusEnum.APPROVED.getValue());
            }
            spcVoyageInfo.add(specialCargoVoyageUpdateReqVo);
        }
        createOrCommitSpcReqVo.setSpcVoyageInfo(spcVoyageInfo);
        if (CollectionUtils.isNotEmpty(attachmentDoList)) {
            List<AttachmentUpdateReqVO> spcAttachmentList = new ArrayList<>(32);
            for (AttachmentDO attachmentDo : attachmentDoList) {
                spcAttachmentList.add(BeanUtil.copyProperties(attachmentDo, AttachmentUpdateReqVO.class, "id", "referenceId"));
            }
            createOrCommitSpcReqVo.setSpcAttachmentList(spcAttachmentList);
        }
        //查询DG信息
        List<SpecialCargoDgDO> specialCargoDgDoList = this.querySpecialDgInfo(specialCargoApplyDo.getId());
        List<Long> dgIds = specialCargoDgDoList.stream().map(SpecialCargoDgDO::getId).collect(Collectors.toList());
        //查询ext信息
        Map<Long, List<SpecialCargoDgExtDO>> extMap = this.querySpecialDgExtInfo(dgIds);
        //查询cas信息
        Map<Long, List<SpecialCargoCasDO>> casMap = this.querySpecialDgCasInfo(dgIds);
        //查询包装信息
        Map<Long, List<SpecialCargoDgPackingDO>> packMap = this.querySpecialDgPackInfo(dgIds);
        //查询关联关系信息
        List<CargoCntrTypeRelationDO> cargoCntrTypeRelationDos = this.querySpecialRelationInfo(specialCargoApplyDo.getId());
        //处理DG货物信息，货物信息和箱信息是多对多的
        List<SpecialCargoDgBaseVO> dgBaseInfo = new ArrayList<>(32);
        for (SpecialCargoDgDO specialCargoDgDo : specialCargoDgDoList) {
            Map<String, String> map = new HashMap<>(4);
            map.put("id", "dgLabel");
            CopyOptions copyOptions = CopyOptions.create().setFieldMapping(map);
            SpecialCargoDgBaseVO specialCargoDgBaseVo = new SpecialCargoDgBaseVO();
            BeanUtil.copyProperties(specialCargoDgDo, specialCargoDgBaseVo, copyOptions);
            specialCargoDgBaseVo.setApplyId(null);
            specialCargoDgBaseVo.setId(null);

            if (!extMap.isEmpty()) {
                List<SpecialCargoDgExtDO> specialCargoDgExtDos = extMap.get(specialCargoDgDo.getId());
                Map<String, String> hashMap = specialCargoDgExtDos.stream().collect(Collectors.toMap(SpecialCargoDgExtDO::getExtName, SpecialCargoDgExtDO::getExtValue));
                specialCargoDgBaseVo.setDgExt((HashMap<String, String>) hashMap);
            }
            if (!casMap.isEmpty()) {
                List<SpecialCargoCasDO> specialCargoCasDoList = casMap.get(specialCargoDgDo.getId());
                List<CasCreateOrUpdateVO> dgCasInfo = new ArrayList<>(32);
                for (SpecialCargoCasDO cargoCasDo : specialCargoCasDoList) {
                    CasCreateOrUpdateVO casCreateOrUpdateVo = BeanUtil.copyProperties(cargoCasDo, CasCreateOrUpdateVO.class, "id", "specialCargoDgId");
                    dgCasInfo.add(casCreateOrUpdateVo);
                }
                specialCargoDgBaseVo.setDgCasInfo(dgCasInfo);
            }
            if (!packMap.isEmpty()) {
                List<SpecialCargoDgPackingDO> specialCargoDgPackingDoList = packMap.get(specialCargoDgDo.getId());
                List<SpecialCargoDgPackingDO> innerDgPack = specialCargoDgPackingDoList.stream().filter(item -> PackingEnum.INNER.getValue().equals(item.getPackingType())).collect(Collectors.toList());
                List<SpecialCargoDgPackingDO> outDgPack = specialCargoDgPackingDoList.stream().filter(item -> PackingEnum.OUTER.getValue().equals(item.getPackingType())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(innerDgPack)) {
                    List<PackingCreateOrUpdateVO> inners = new ArrayList<>(32);
                    for (SpecialCargoDgPackingDO inner : innerDgPack) {
                        inners.add(BeanUtil.copyProperties(inner, PackingCreateOrUpdateVO.class, "id", "dgId"));
                    }
                    specialCargoDgBaseVo.setInnerDgPacking(inners);
                }
                if (CollectionUtils.isNotEmpty(outDgPack)) {
                    List<PackingCreateOrUpdateVO> outs = new ArrayList<>(32);
                    for (SpecialCargoDgPackingDO out : outDgPack) {
                        outs.add(BeanUtil.copyProperties(out, PackingCreateOrUpdateVO.class, "id", "dgId"));
                    }
                    specialCargoDgBaseVo.setOuterDgPacking(outs);
                }
            }
            dgBaseInfo.add(specialCargoDgBaseVo);
        }
        cntrAndDgBaseVo.setDgBaseInfo(dgBaseInfo);
        //处理箱信息
        List<SpecialCargoCntrBaseVO> cntrBaseInfo = new ArrayList<>(32);
        for (SpecialCargoCntrDO specialCargoCntrDo : cntrDoList) {
            SpecialCargoCntrBaseVO specialCargoCntrBaseVo = BeanUtil.copyProperties(specialCargoCntrDo, SpecialCargoCntrBaseVO.class, "id", "applyId");
            List<Long> cargoDgIds = cargoCntrTypeRelationDos.stream().filter(item -> specialCargoCntrDo.getId().equals(item.getCntrId())).map(CargoCntrTypeRelationDO::getDgId).collect(Collectors.toList());
            specialCargoCntrBaseVo.setDgLabels(cargoDgIds);
            cntrBaseInfo.add(specialCargoCntrBaseVo);
        }
        cntrAndDgBaseVo.setCntrBaseInfo(cntrBaseInfo);
        createOrCommitSpcReqVo.setCntrAndDgInfos(cntrAndDgBaseVo);
        return createOrCommitSpcReqVo;
    }

    /**
     * 处理OOG
     *
     * @param specialCargoApplyDo
     * @param specialModifyVelVoyDto
     * @return
     */
    public CreateOrCommitSpcReqVO dealOogInfo(SpecialCargoApplyDO specialCargoApplyDo, SpecialModifyVelVoyDto specialModifyVelVoyDto) {
        CreateOrCommitSpcReqVO createOrCommitSpcReqVo = new CreateOrCommitSpcReqVO();
        //查询箱信息
        List<SpecialCargoCntrDO> cntrDoList = this.querySpecialCntrInfo(specialCargoApplyDo.getId());
        //查询附件信息
        List<AttachmentDO> attachmentDoList = this.querySpecialAttachInfo(specialCargoApplyDo.getId());
        //查询船名航次信息
        List<SpecialCargoVoyageDO> voyageDoList = this.querySpecialVelVoyInfo(specialCargoApplyDo.getId(), specialModifyVelVoyDto);
        //查询OOG
        List<Long> cntrIds = cntrDoList.stream().map(SpecialCargoCntrDO::getId).collect(Collectors.toList());
        List<SpecialCargoOogDO> cargoOdoDoList = this.queryOogInfo(cntrIds);
        Map<Long, List<SpecialCargoOogDO>> listMap = cargoOdoDoList.stream().collect(Collectors.groupingBy(SpecialCargoOogDO::getCntrId));
        specialCargoApplyDo.setSoId(specialModifyVelVoyDto.getNewSoId());
        createOrCommitSpcReqVo = BeanUtil.copyProperties(specialCargoApplyDo, createOrCommitSpcReqVo.getClass(), "id");
        createOrCommitSpcReqVo.setCommitOrSave(true);
        createOrCommitSpcReqVo.setPartnerFlag(false);
        //设置4港信息
        SoDO soDo = soMapper.selectById(specialModifyVelVoyDto.getNewSoId());
        createOrCommitSpcReqVo.setPodCode(soDo.getPodCode());
        createOrCommitSpcReqVo.setPolCode(soDo.getPolCode());
        createOrCommitSpcReqVo.setPorCode(soDo.getPorCode());
        createOrCommitSpcReqVo.setDelCode(soDo.getDelCode());
        createOrCommitSpcReqVo.setCurrentPort(soDo.getCurrentPort());

        createOrCommitSpcReqVo.setApplyStatus(ApplyStatusEnum.CHANGEVOYCHECK.getValue());
        List<SpecialCargoVoyageUpdateReqVO> spcVoyageInfo = new ArrayList<>(32);
        for (SpecialCargoVoyageDO specialCargoVoyageDo : voyageDoList) {
            SpecialCargoVoyageUpdateReqVO specialCargoVoyageUpdateReqVo = BeanUtil.copyProperties(specialCargoVoyageDo, SpecialCargoVoyageUpdateReqVO.class, "id", "applyId");
            if (ApproveStatusEnum.PENDING.getValue().equals(specialCargoVoyageUpdateReqVo.getRouteApproveStatus())) {
                specialCargoVoyageUpdateReqVo.setRouteApproveStatus(ApprovalStatusEnum.PENDING.getValue());
            }
            if (ApproveStatusEnum.APPROVED.getValue().equals(specialCargoVoyageUpdateReqVo.getRouteApproveStatus())) {
                specialCargoVoyageUpdateReqVo.setRouteApproveStatus(ApprovalStatusEnum.APPROVED.getValue());
            }
            spcVoyageInfo.add(specialCargoVoyageUpdateReqVo);
        }
        createOrCommitSpcReqVo.setSpcVoyageInfo(spcVoyageInfo);
        if (CollectionUtils.isNotEmpty(attachmentDoList)) {
            List<AttachmentUpdateReqVO> spcAttachmentList = new ArrayList<>(32);
            for (AttachmentDO attachmentDo : attachmentDoList) {
                spcAttachmentList.add(BeanUtil.copyProperties(attachmentDo, AttachmentUpdateReqVO.class, "id", "referenceId"));
            }
            createOrCommitSpcReqVo.setSpcAttachmentList(spcAttachmentList);
        }
        List<CntrAndOogBaseVO> cntrAndOogInfos = new ArrayList<>(32);
        for (SpecialCargoCntrDO specialCargoCntrDo : cntrDoList) {
            CntrAndOogBaseVO cntrAndOogBaseVo = new CntrAndOogBaseVO();
            cntrAndOogBaseVo.setCntrBaseInfo(BeanUtil.copyProperties(specialCargoCntrDo, SpecialCargoCntrBaseVO.class, "id", "applyId"));
            SpecialCargoOogDO specialCargoOogDo = listMap.get(specialCargoCntrDo.getId()).get(0);
            cntrAndOogBaseVo.setOogBaseInfo(BeanUtil.copyProperties(specialCargoOogDo, SpecialCargoOogBaseVO.class, "id", "cntrId"));
            cntrAndOogInfos.add(cntrAndOogBaseVo);
        }
        createOrCommitSpcReqVo.setCntrAndOogInfos(cntrAndOogInfos);
        return createOrCommitSpcReqVo;
    }

    /**
     * 箱信息
     *
     * @param applyId
     * @return
     */
    public List<SpecialCargoCntrDO> querySpecialCntrInfo(Long applyId) {
        LambdaQueryWrapperX<SpecialCargoCntrDO> specialCargoCntrWrapperX = new LambdaQueryWrapperX<>();
        specialCargoCntrWrapperX.eq(SpecialCargoCntrDO::getApplyId, applyId);
        return specialCargoCntrMapper.selectList(specialCargoCntrWrapperX);
    }

    /**
     * 附件信息
     *
     * @param applyId
     * @return
     */
    public List<AttachmentDO> querySpecialAttachInfo(Long applyId) {
        //特种货附件
        LambdaQueryWrapperX<AttachmentDO> specialAttachmentWrapperX = new LambdaQueryWrapperX<>();
        specialAttachmentWrapperX.eq(AttachmentDO::getReferenceId, applyId).eq(AttachmentDO::getReferenceType, SoSiEnum.SPC.getValue());
        return attachmentMapper.selectList(specialAttachmentWrapperX);
    }

    /**
     * 船名航次信息
     *
     * @param applyId
     * @param specialModifyVelVoyDto
     * @return
     */
    public List<SpecialCargoVoyageDO> querySpecialVelVoyInfo(Long applyId, SpecialModifyVelVoyDto specialModifyVelVoyDto) {
        List<SpecialCargoVoyageDO> specialCargoVoyageDo = SpecialCargoVoyageConvert.INSTANCE.convertSpecialCargoVoyageDos(specialModifyVelVoyDto.getSoVslvoyList());
        specialCargoVoyageDo.forEach(item -> {
            item.setApplyId(applyId);
            item.setId(null);
        });
        return specialCargoVoyageDo;
    }

    /**
     * odo信息
     *
     * @param cntrIds
     * @return
     */
    public List<SpecialCargoOdoDO> querySpecialOdoInfo(List<Long> cntrIds) {
        LambdaQueryWrapperX<SpecialCargoOdoDO> specialCargoOdoWrapperX = new LambdaQueryWrapperX<>();
        specialCargoOdoWrapperX.inIfPresent(SpecialCargoOdoDO::getCntrId, cntrIds);
        return specialCargoOdoMapper.selectList(specialCargoOdoWrapperX);
    }

    /**
     * flex信息
     *
     * @param cntrIds
     * @return
     */
    public List<SpecialCargoFlexiDO> querySpecialFlexInfo(List<Long> cntrIds) {
        LambdaQueryWrapperX<SpecialCargoFlexiDO> specialCargoFlexiWrapperX = new LambdaQueryWrapperX<>();
        specialCargoFlexiWrapperX.inIfPresent(SpecialCargoFlexiDO::getCntrId, cntrIds);
        return specialCargoFlexiMapper.selectList(specialCargoFlexiWrapperX);
    }

    /**
     * AK/oog信息
     *
     * @param cntrIds
     * @return
     */
    public List<SpecialCargoOogDO> queryOogInfo(List<Long> cntrIds) {
        LambdaQueryWrapperX<SpecialCargoOogDO> specialCargoOogWrapperX = new LambdaQueryWrapperX<>();
        specialCargoOogWrapperX.inIfPresent(SpecialCargoOogDO::getCntrId, cntrIds);
        return specialCargoOogMapper.selectList(specialCargoOogWrapperX);
    }

    /**
     * Dg信息
     *
     * @param applyId
     * @return
     */
    public List<SpecialCargoDgDO> querySpecialDgInfo(Long applyId) {
        return specialCargoDgMapper.selectList(new LambdaQueryWrapper<SpecialCargoDgDO>().eq(SpecialCargoDgDO::getApplyId, applyId));
    }

    /**
     * 获取关联关系
     *
     * @param applyId
     * @return
     */
    public List<CargoCntrTypeRelationDO> querySpecialRelationInfo(Long applyId) {
        return cargoCntrTypeRelationMapper.selectList(new LambdaQueryWrapperX<CargoCntrTypeRelationDO>().eq(CargoCntrTypeRelationDO::getApplyId, applyId));
    }

    /**
     * 获取Dg的cas信息
     *
     * @param dgIds
     * @return
     */
    public Map<Long, List<SpecialCargoCasDO>> querySpecialDgCasInfo(List<Long> dgIds) {
        Map<Long, List<SpecialCargoCasDO>> map = new HashMap<>(32);
        LambdaQueryWrapperX<SpecialCargoCasDO> specialCargoCasDoWrapperX = new LambdaQueryWrapperX<>();
        specialCargoCasDoWrapperX.inIfPresent(SpecialCargoCasDO::getSpecialCargoDgId, dgIds);
        List<SpecialCargoCasDO> specialCargoCasDoList = specialCargoCasMapper.selectList(specialCargoCasDoWrapperX);
        if (CollectionUtils.isNotEmpty(specialCargoCasDoList)) {
            map = specialCargoCasDoList.stream().collect(Collectors.groupingBy(SpecialCargoCasDO::getSpecialCargoDgId));
        }
        return map;
    }

    /**
     * 获取Dg的ext信息
     *
     * @param dgIds
     * @return
     */
    public Map<Long, List<SpecialCargoDgExtDO>> querySpecialDgExtInfo(List<Long> dgIds) {
        List<SpecialCargoDgExtDO> specialCargoDgExtDos = specialCargoDgExtMapper.selectList(new LambdaQueryWrapperX<SpecialCargoDgExtDO>().inIfPresent(SpecialCargoDgExtDO::getDgId, dgIds));
        Map<Long, List<SpecialCargoDgExtDO>> extMap = new HashMap<>(32);
        if (CollectionUtils.isNotEmpty(specialCargoDgExtDos)) {
            extMap = specialCargoDgExtDos.stream().collect(Collectors.groupingBy(SpecialCargoDgExtDO::getDgId));
        }
        return extMap;
    }

    /**
     * 获取dg的包装代码
     *
     * @param dgIds
     * @return
     */
    public Map<Long, List<SpecialCargoDgPackingDO>> querySpecialDgPackInfo(List<Long> dgIds) {
        Map<Long, List<SpecialCargoDgPackingDO>> map = new HashMap<>(32);
        List<SpecialCargoDgPackingDO> specialCargoDgPackingDoList = specialCargoDgPackingMapper.selectList(new LambdaQueryWrapperX<SpecialCargoDgPackingDO>().inIfPresent(SpecialCargoDgPackingDO::getDgId, dgIds));
        if (CollectionUtils.isNotEmpty(specialCargoDgPackingDoList)) {
            map = specialCargoDgPackingDoList.stream().collect(Collectors.groupingBy(SpecialCargoDgPackingDO::getDgId));
        }
        return map;
    }
}
